#include "angelscript_editor_extension.hpp"
#include <cassert>
#include "angelscript.h"
#include "angelscript_base.hpp"
#include "scripting/scripting_api.h"
#include "scripting/scripting_module.h"

void AngelScriptEditorExtension::execute (const void *node)
{
    auto engine = AngelScriptShared::GetEngine ();
    auto module = engine->GetModule (module_name.c_str (), asGM_ONLY_IF_EXISTS);  // 这里始终要创建模块
    assert (module != nullptr && "Module missing?");

    auto ctx = engine->CreateContext ();

    asIScriptFunction *main_func = nullptr;
    switch (apply_target_)
    {
    case IEditorScript::eItem: main_func = module->GetFunctionByDecl ("void main(const ItemNode&)"); break;
    case IEditorScript::eDay: main_func = module->GetFunctionByDecl ("void main(const DailyItem&)"); break;
    case IEditorScript::eMonth: main_func = module->GetFunctionByDecl ("void main(const MonthlyItem&)"); break;
    case IEditorScript::eYear: main_func = module->GetFunctionByDecl ("void main(const YearlyItem&)"); break;
    default: break;
    }

    if (!main_func)
    {
        ctx->Release ();
    }
    else
    {

        ctx->Prepare (main_func);
        ctx->SetArgAddress (0, (void *) node);
        ctx->Execute ();
        ctx->Release ();
    }
}

IScript *AngelScriptEditorExtension::create (IEditorScript::EditorTarget target, std::string title, const std::string_view &code,
                                             const std::string &script_path)
{
    auto engine = AngelScriptShared::GetEngine ();
    (void) engine;

    AngelScriptEditorExtension *e = new AngelScriptEditorExtension (target, std::move (title), script_path);
    if (!e->compile (code))
    {
        delete e;
        e = nullptr;
    }

    return e;
}

bool AngelScriptEditorExtension::compile (const std::string_view &code)
{
    auto engine = AngelScriptShared::GetEngine ();
    auto module = engine->GetModule (module_name.c_str (), asGM_ALWAYS_CREATE);  // 这里始终要创建模块
    module->AddScriptSection ("Main", code.data ());
    if (module->Build () < 0)
    {
        return false;
    }
    return true;
}

AngelScriptEditorExtension::AngelScriptEditorExtension (IEditorScript::EditorTarget type, std::string title, const std::string &script_path) :
    IEditorScript (type, title, script_path, g_current_module), AngelScriptBase (script_path, "Editor")
{
}

AngelScriptEditorExtension::~AngelScriptEditorExtension () {}
